﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Tum.CollabXT;
using Tum.CollabXT.DocxGen.Resources;
using System.Xml;

namespace Tum.CollabXT.DocxGen
{
    public class DocxGen : IToolProvider
    {
        public Dictionary<string, object> ExtendedData
        {
            get { return _ExtendedData; }
        }
        Dictionary<string, object> _ExtendedData = new Dictionary<string,object>();

        /// <summary>
        /// Name of the project.
        /// </summary>
        public string ProjectName
        {
            get { return _ProjectName; }
            set { _ProjectName = value; }
        }
        private string _ProjectName;

        /// <summary>
        /// Output path for the generated product templates.
        /// </summary>
        public string OutputPath
        {
            get { return _OutputPath; }
            set { _OutputPath = value; }
        }
        private string _OutputPath;

        /// <summary>
        /// Path of the templates to be used for the conversion. (MasterTemplate.{docx|dotx})
        /// </summary>
        public string TemplatePath
        {
            get { return _TemplatePath; }
            set { _TemplatePath = value; }
        }
        private string _TemplatePath;

        public HashSet<string> ProductsToGenerated { get; private set; }


        Log _Log = null;
        internal IProcessProvider _ProcessProvider;


        const string DocMasterTemplateFileName = "MasterTemplate.docx";
        const string DotMasterTemplateFileName = "MasterTemplate.dotx";

        /// <summary>
        /// Initialize the provider.
        /// </summary>
        /// <param name="processProvider">The process provider to be used for input data.</param>
        /// <param name="log">Log to be used.</param>
        public void Initialize(IProcessProvider processProvider, Log log)
        {
            _ProcessProvider = processProvider;
            _Log = log;

            if(ProductsToGenerated == null)
                ProductsToGenerated = new HashSet<string>();
        }

        /// <summary>
        /// Processes the data and generates the document templates.
        /// </summary>
        public void Process()
        {
            #region Preparations
            if (_ProcessProvider == null)
                throw new DocxGenException("ProcessProvider has not been set. Call Initialize before.");

            if (!Directory.Exists(TemplatePath))
                throw new DocxGenException("Template folder does not exist");

            if (!_OutputPath.EndsWith("/", StringComparison.OrdinalIgnoreCase) && !_OutputPath.EndsWith("\\", StringComparison.OrdinalIgnoreCase))
                _OutputPath += "/";

            if (!_TemplatePath.EndsWith("/", StringComparison.OrdinalIgnoreCase) && !_TemplatePath.EndsWith("\\", StringComparison.OrdinalIgnoreCase))
                _TemplatePath += "/";

            Directory.CreateDirectory(_OutputPath);
            #endregion

            //Initialize DocumentGenerator instance
            DocumentGenerator docGen = new DocumentGenerator(_Log);

            docGen.OutputPath = OutputPath;
            docGen.ProjectName = ProjectName;

            //Check if template files exist
            if (!File.Exists(_TemplatePath + DocMasterTemplateFileName))
                throw new DocxGenException(string.Format(Language.Error_TemplateFileNotFound, DocMasterTemplateFileName));
            if (!File.Exists(_TemplatePath + DotMasterTemplateFileName))
                throw new DocxGenException(string.Format(Language.Error_TemplateFileNotFound, DotMasterTemplateFileName));

            docGen.TemplateDocxPath = _TemplatePath + DocMasterTemplateFileName;
            docGen.TemplateDotxPath = _TemplatePath + DotMasterTemplateFileName;

            //Generate documents
            docGen.GenerateDocuments(_ProcessProvider, ProductsToGenerated);
        }

        /// <summary>
        /// Gets the name of the XAML config page.
        /// </summary>
        /// <returns>XAML config page name.</returns>
        public string GetConfigPageName()
        {
            return "DocxConfigPage.xaml";
        }

        /// <summary>
        /// Gets the name of the DocX provider.
        /// </summary>
        /// <returns>DocX provider name.</returns>
        public static string GetProviderName()
        {
            return Language.ProviderInfo_Name;
        }

        /// <summary>
        /// Gets the provider's description.
        /// </summary>
        /// <returns>Provider description.</returns>
        public static string GetProviderDescription()
        {
            return Language.ProviderInfo_Description;
        }

        /// <summary>
        /// Gets the provider's author.
        /// </summary>
        /// <returns>Provider author.</returns>
        public static string GetProviderAuthor()
        {
            return "© 2009 TU München";
        }


        public void Serialize(System.Xml.XmlNode outputParentNode)
        {
            XmlDocument xmlDoc = outputParentNode.OwnerDocument;

            XmlNode settingsNode = xmlDoc.CreateElement("settings");
            outputParentNode.AppendChild(settingsNode);

            XmlAttribute outputPathAttribute = xmlDoc.CreateAttribute("outputPath");
            outputPathAttribute.Value = OutputPath;
            settingsNode.Attributes.Append(outputPathAttribute);

            XmlAttribute templatePathAttribute = xmlDoc.CreateAttribute("templatePath");
            templatePathAttribute.Value = TemplatePath;
            settingsNode.Attributes.Append(templatePathAttribute);

            XmlAttribute projectNameAttribute = xmlDoc.CreateAttribute("projectName");
            projectNameAttribute.Value = ProjectName;
            settingsNode.Attributes.Append(projectNameAttribute);


            XmlNode selectedProductsNode = xmlDoc.CreateElement("products");
            settingsNode.AppendChild(selectedProductsNode);

            foreach (string curProd in ProductsToGenerated)
            {
                XmlNode newProductNode = xmlDoc.CreateElement("product");
                selectedProductsNode.AppendChild(newProductNode);

                XmlAttribute productIdAttribute = xmlDoc.CreateAttribute("id");
                productIdAttribute.Value = curProd;
                newProductNode.Attributes.Append(productIdAttribute);
            }


        }

        public void Deserialize(System.Xml.XmlNode inputParentNode)
        {
            XmlNode settingsNode = inputParentNode.SelectSingleNode("settings");
            ProductsToGenerated = new HashSet<string>();

            try
            {
                _OutputPath = null;
                _OutputPath = settingsNode.Attributes["outputPath"].Value;
            }
            catch { }

            try
            {
                _TemplatePath = null;
                _TemplatePath = settingsNode.Attributes["templatePath"].Value;
                if (!Directory.Exists(_TemplatePath))
                    _TemplatePath = null;
            }
            catch { }

            try
            {
                _ProjectName = null;
                _ProjectName = settingsNode.Attributes["projectName"].Value;
            }
            catch { }

            try
            {
                XmlNodeList selectedProductNodes = settingsNode.SelectNodes("products/product");
                foreach (XmlNode curSelectedProd in selectedProductNodes)
                {
                    try
                    {
                        ProductsToGenerated.Add(curSelectedProd.Attributes["id"].Value.ToLower());
                    }
                    catch { }
                }
            }
            catch { }
        }
    }
}
